package uk.ac.bbsrc.babraham.FastQC.Modules;

import java.awt.BorderLayout;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableModel;

import uk.ac.bbsrc.babraham.FastQC.Report.HTMLReportArchive;
import uk.ac.bbsrc.babraham.FastQC.Sequence.Sequence;

public class FilterOverRepresentedSeqs implements QCModule {
	protected HashMap<String, ArrayList<Sequence>> sequences = new HashMap<String, ArrayList<Sequence>>();
	private String GoodSeqsFilename = new String();
	private String BadSeqsFilename = new String();
	private final String newline = new String("\n");
	private final String GoodSeqsFilePrefix = new String("Good_");
	private final String BadSeqsFilePrefix = new String("Bad_");
	private boolean calculated = false;
	private int totalcount = 0;
	private final int HashKeyLength = 50;
	private final double PercentageLimit = 0.1;
	
	public String description() {
		return "Filter out sequences which are overrepresented in the set";
	}

	@Override
	public void processSequence(Sequence sequence) {
		ArrayList<Sequence> value = new ArrayList<Sequence>();
		
		calculated = false;
		++totalcount;
		
		if (GoodSeqsFilename.length() == 0) {
			GoodSeqsFilename = GoodSeqsFilePrefix + sequence.file().name();
			BadSeqsFilename = BadSeqsFilePrefix + sequence.file().name();
		}
			
		String seq = sequence.getSequence();
		if (seq.length()>=HashKeyLength){
			seq = new String(seq.substring(0, HashKeyLength));
			if (sequences.containsKey(seq)) {
				value = (ArrayList<Sequence>) sequences.get(seq);	
			} 
			value.add(sequence);
			sequences.put(seq, value);
		}		
	}
	private synchronized void getFilterOverrepresentedSeqs () throws IOException{
		// Identify over-represented sequences and save them into files
		// TODO Open files for writing
		File badfile = new File(BadSeqsFilename);
		File goodfile = new File(GoodSeqsFilename);
		Writer badoutput = new BufferedWriter(new FileWriter(badfile));
		Writer goodoutput = new BufferedWriter(new FileWriter(goodfile));
		Writer filetowrite;
		String seq;
		Sequence tmp;
		
		ArrayList<Sequence> value;
		Iterator<String> s = sequences.keySet().iterator();
		Iterator<Sequence> m;
		while (s.hasNext()) {
			seq = s.next();
			value = sequences.get(seq);
			m = value.iterator();
			double percentage = ((double)value.size()/totalcount)*100;
			if (percentage > PercentageLimit) {
				// Bad sequences
				filetowrite = badoutput;
			} else {
				// Good sequences
				filetowrite = goodoutput;
			}
			while (m.hasNext()){
				tmp = m.next();
				filetowrite.write(tmp.getID() + newline);
				filetowrite.write(tmp.getSequence() + newline);
				filetowrite.write("+" + Double.toString(percentage) + "|" + Integer.toString(value.size()) + newline);
				// filetowrite.write("+" + newline);
				filetowrite.write(tmp.getQualityString() + newline);
			}
		}
		
		// Close files
		badoutput.close();
		goodoutput.close();
	}
	
	@Override
	public JPanel getResultsPanel() {
		JPanel returnPanel = new JPanel();
		returnPanel.setLayout(new BorderLayout());
		returnPanel.add(new JLabel("Filter out overrepresented sequences",JLabel.CENTER),BorderLayout.NORTH);
		
		if (!calculated)
			try {
				getFilterOverrepresentedSeqs();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		
		returnPanel.add(new JLabel("Data has been written to files...",JLabel.CENTER),BorderLayout.CENTER);

		
		return returnPanel;
	}

	@Override
	public String name() {
		return "Filter out overrepresented sequences";
	}

	@Override
	public void reset() {
		GoodSeqsFilename = new String();
		BadSeqsFilename = new String();
		totalcount = 0;
		sequences.clear();
	}

	@Override
	public boolean raisesError() {
		// No error to be raised
		return false;
	}

	@Override
	public boolean raisesWarning() {
		// No warning to be raised
		return false;
	}

	@Override
	public boolean ignoreFilteredSequences() {
		// Do not apply filter
		return true;
	}

	@Override
	public void makeReport(HTMLReportArchive report) throws IOException {
		// When the main program calling this function, write data to file
		if (!calculated) getFilterOverrepresentedSeqs ();
		
	}
	

}
